package com.billow.net.rtmp
{
	import com.billow.events.RtmpServerEvent;
	import com.billow.net.Client;
	
	import flash.desktop.NativeApplication;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.ServerSocketConnectEvent;
	import flash.net.ObjectEncoding;
	import flash.net.ServerSocket;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	
	[Event(name = "client_close", type = "com.billow.events.RtmpServerEvent")]
	[Event(name = "client_handShake", type = "com.billow.events.RtmpServerEvent")]
	[Event(name = "client_invokeName", type = "com.billow.events.RtmpServerEvent")]
	
	public class RtmpServer extends EventDispatcher
	{
		private const _rtmpStream:RtmpStream = new RtmpStream();
		private const _users:Dictionary = new Dictionary();
		private var _rtmpServerEvent:RtmpServerEvent;
		private var _serverSocket:ServerSocket;
		private var _id:uint;
		
		
		public function RtmpServer()
		{
			NativeApplication.nativeApplication.addEventListener(Event.EXITING ,exitHandler);
		}
		
		
		
		
		
		
		
		///////////////////////////////////////////////////////////////////////////////
		//
		// Public
		//
		//////////////////////////////////////////////////////////////////////////////
		
		public function get userNum():uint 
		{
			var len:int = 0;
			for(var key:* in _users)
				len++;
			return len;
		}
		
		/**
		 * 打开服务器 
		 * @param localAddress
		 * @param localPort
		 * 
		 */		
		public function bind(localAddress:String ,localPort:int):void
		{
			try{
				_serverSocket = new ServerSocket();
				if(_serverSocket.bound)
				{
					close();
					_serverSocket = new ServerSocket();
				}
				_serverSocket.bind(localPort, localAddress);
				_serverSocket.addEventListener(ServerSocketConnectEvent.CONNECT, clientConnect);
				_serverSocket.listen();
				
				(_serverSocket.bound && _serverSocket.listening)?trace("RTMP服务器 成功开启"):trace("RTMP服务器 开启失败");
			}catch(e:Error){
				trace("RTMP服务器 开启失败");
			}
		}
		
		/**
		 * 关闭服务器 
		 * 
		 */		
		public function close():void
		{
			for (var key:String in _users)
			{
				var client:ClientControl = _users[key];
				client.removeEventListener(ClientControlEvent.CLIENT_CLOSE ,clientControlEventHandler);
				client.removeEventListener(ClientControlEvent.CLIENT_HANDSHAKE ,clientControlEventHandler);
				client.removeEventListener(ClientControlEvent.CLIENT_MEDIA ,clientControlEventHandler);
				client.removeEventListener(ClientControlEvent.CLIENT_INVOKENAME ,clientControlEventHandler);
				client.close();
				_users[key] = null;
				delete _users[key];
			}
			
			if(_serverSocket!=null)
			{
				if(_serverSocket.bound)_serverSocket.close();
				_serverSocket.removeEventListener(ServerSocketConnectEvent.CONNECT, clientConnect);
				_serverSocket = null;
			}
		}
		
		
		/**
		 * 广播消息 
		 * @param messageName
		 * @param params
		 * 
		 */		
		public function broadcastMessage(messageName:String, message:Object):void
		{
			broadcastPacket(RtmpPacketManage.message(messageName ,message));
		}
		
		/**
		 * 指定ID 发送消息 
		 * @param id
		 * @param messageName
		 * @param params
		 * 
		 */
		public function sendMessage(id:String, messageName:String, message:Object):void
		{
			if(_users[id]!=null)
				_users[id].sendPacket(RtmpPacketManage.message(messageName ,message));
		}
		
		
		///////////////////////////////////////////////////////////////////////////////
		//
		// Handler
		//
		//////////////////////////////////////////////////////////////////////////////
		
		private function broadcast(bytes:ByteArray):void
		{
			for (var key:String in _users)
				_users[key].send(bytes);
		}
		
		private function broadcastPacket(packet:RtmpPacket):void
		{
			for (var key:String in _users)
				_users[key].sendPacket(packet);
		}
		
		
		
		///////////////////////////////////////////////////////////////////////////////
		//
		// Event
		//
		//////////////////////////////////////////////////////////////////////////////
		
		private function exitHandler(event:Event):void
		{
			trace("exiting...");
			close();
		}
		
		
		/** 客户端连接 */
		private function clientConnect(event:ServerSocketConnectEvent):void
		{
			_id++;
			var id:String = "user_"+_id;
			var client:ClientControl = new ClientControl(event.socket ,id ,ObjectEncoding.AMF0);
			client.addEventListener(ClientControlEvent.CLIENT_CLOSE ,clientControlEventHandler);
			client.addEventListener(ClientControlEvent.CLIENT_HANDSHAKE ,clientControlEventHandler);
			client.addEventListener(ClientControlEvent.CLIENT_MEDIA ,clientControlEventHandler);
			client.addEventListener(ClientControlEvent.CLIENT_INVOKENAME ,clientControlEventHandler);
			_users[id] = client;
			//trace("服务器消息(server)："+client.info.id+" 握手中...");
		}
		
		/** 客户端事件 */
		private function clientControlEventHandler(event:ClientControlEvent):void
		{
			var client:ClientControl = event.target as ClientControl;
			
			switch(event.type)
			{
				case ClientControlEvent.CLIENT_HANDSHAKE:
					/** 客户端握手成功 */
					
					//拒绝该用户
					//client.sendPacket(RtmpPacketManage.rejectConnectMessage(client.info.objectEncoding, 1));
					//client.close();
					
					//接受该用户
					client.sendPacket(RtmpPacketManage.acceptConnectMessage(client.info.objectEncoding, 1));
					
					_rtmpServerEvent = new RtmpServerEvent(RtmpServerEvent.CLIENT_HANDSHAKE ,client.info);
					dispatchEvent(_rtmpServerEvent);
					return;
					
				case ClientControlEvent.CLIENT_CLOSE:
					/** 客户端断开 */
					_rtmpStream.closeCheck(client);
					
					if(_users[client.info.id]!=null)
						delete _users[client.info.id];
					
					client.removeEventListener(ClientControlEvent.CLIENT_CLOSE ,clientControlEventHandler);
					client.removeEventListener(ClientControlEvent.CLIENT_HANDSHAKE ,clientControlEventHandler);
					client.removeEventListener(ClientControlEvent.CLIENT_MEDIA ,clientControlEventHandler);
					client.removeEventListener(ClientControlEvent.CLIENT_INVOKENAME ,clientControlEventHandler);
					client.close();
					
					_rtmpServerEvent = new RtmpServerEvent(RtmpServerEvent.CLIENT_CLOSE ,client.info);
					dispatchEvent(_rtmpServerEvent);
					return;
					
				case ClientControlEvent.CLIENT_MEDIA:
					/** Media */
					_rtmpStream.broadcastStream(client.packet);
					return;
					
					
				case ClientControlEvent.CLIENT_INVOKENAME:
					/** 客户端握消息 */
					switch(client.info.invokeName)
					{
						case "createStream":	_rtmpStream.onCreateStream(client ,client.packet);			break;
						case "publish":		_rtmpStream.onPublish(client ,client.packet);				break;
						case "play":			_rtmpStream.onPlay(client ,client.packet);					break;
						case "deleteStream":	_rtmpStream.onDeleteStream(client.packet);					break;
						case "closeStream":	_rtmpStream.onCloseStream(client ,client.packet);			break;
						case "startTransmit":	/*要求服务器发送更多缓存中*/								break;
						case "stopTransmit":	/*要求服务暂停发送到客户端*/								break;
						default:
							_rtmpServerEvent = new RtmpServerEvent(RtmpServerEvent.CLIENT_INVOKENAME ,client.info);
							dispatchEvent(_rtmpServerEvent);
							break;
					}
					return;
			}
		}
	}
}